<template>
  <div class="app-container">
    <el-row>
      <el-col>
        <el-button class="margin-right" type="text" icon="el-icon-refresh" @click="reloadAllConnects" />

        <el-select v-model="connParam.connName" size="small" @change="switchConnect">
          <el-option v-for="connect in connects" :key="connect" :value="connect" :label="connect" />
        </el-select>
        <el-select v-model="connParam.index" size="small" :disabled="tabs.dashboard.connInfo.redisRunMode === 'cluster'" style="width: 60px" @change="switchIndex">
          <el-option v-for="db in dbsComputed" :key="db" :value="db" :label="db" />
        </el-select>
      </el-col>
    </el-row>

    <el-tabs :active-name="tabs.activeTabName" @tab-click="switchTab">
      <!-- 监控运行模式, 节点信息 -->
      <el-tab-pane name="dashboard" label="监控总览">
        <p class=" text-forestgreen">点击节点显示节点信息</p>
        <p>运行模式: <b>{{ tabs.dashboard.connInfo.redisRunMode }}</b></p>
        <el-row>
          <el-col :span="8">
            <el-tree :data="tabs.dashboard.connInfo.masterNodes" :expand-on-click-node="false" :default-expand-all="true" :props="defaultProps" @node-click="clickNode">
              <div slot-scope="{ node, data }" class="custom-tree-node">
                <b class="margin-right">{{ data.role }}</b>
                <span v-if="data.hostAndPort">{{ data.hostAndPort.host }}:{{ data.hostAndPort.port }}</span>
                <span v-if="tabs.dashboard.connInfo.redisRunMode === 'cluster' && data.role == 'master' ">
                  <!-- 集群模式显示槽位信息 -->
                  {{ data.slotStart }} - {{ data.slotEnd }}
                </span>

                <!--                <el-button type="text" size="small"  class="text-danger " @click="loadNodeInfo(data)" >节点信息</el-button>-->
              </div>
            </el-tree>
          </el-col>
          <el-col v-show="nodeInfoTabs.nodeId" :span="15" class="margin-left">
            <div>当前节点:
              <span v-if="nodeInfoTabs.node.hostAndPort">{{ nodeInfoTabs.node.hostAndPort.host }}:{{ nodeInfoTabs.node.hostAndPort.port }}</span>
              <span v-else>{{ nodeInfoTabs.nodeId }}</span>
            </div>
            <el-tabs class="" :active-name="nodeInfoTabs.activeTabName" @tab-click="switchNodeInfoTab">
              <el-tab-pane name="clients" :label="nodeInfoTabs.clients.title">
                <span style="display: block" class="margin-bottom"><b>总连接数: </b>{{ nodeInfoTabs.clients.data.length }}</span>
                <el-table
                  :data="clients"
                  border
                  stripe
                  style="width: 100%"
                  size="mini"
                  height="400"
                >
                  <el-table-column
                    prop="id"
                    label="id"
                  />
                  <el-table-column
                    label="client"
                    sortable
                    width="150"
                  >
                    <template slot-scope="scope">
                      <span>{{ scope.row.connect.host + ':' + scope.row.connect.port }}</span>
                    </template>
                  </el-table-column>
                  <el-table-column
                    prop="age"
                    label="age"
                    sortable
                  />
                  <el-table-column
                    prop="idle"
                    label="idle"
                    sortable
                  />
                  <el-table-column
                    prop="cmd"
                    label="cmd"
                    sortable
                  />
                  <el-table-column
                    fixed="right"
                    label="操作"
                    width="150"
                  >
                    <template slot-scope="scope">
                      <el-button type="text" class="text-danger" size="small" @click="killClient(scope.row.connect,nodeInfoTabs.nodeId)">kill</el-button>
                    </template>
                  </el-table-column>
                </el-table>
                <!--分页组件-->
                <el-pagination
                  :current-page="nodeInfoTabs.clients.currentPage"
                  :page-size="nodeInfoTabs.clients.pageSize"
                  layout="total, sizes, prev, pager, next"
                  :total="nodeInfoTabs.clients.data.length"
                  @size-change="handleNodeInfoTabSizeChange"
                  @current-change="handleNodeInfoTabCurrentChange"
                />
              </el-tab-pane>
              <el-tab-pane name="memory" :label="nodeInfoTabs.memory.title">
                <ul class="memory-show" style="">
                  <li><label for="">rss:</label> {{ formatSizeHuman(nodeInfoTabs.memory.data.rss) }}</li>
                  <li><label for="">max:</label> {{ formatSizeHuman(nodeInfoTabs.memory.data.max) }}</li>
                  <li><label for="">system:</label> {{ formatSizeHuman(nodeInfoTabs.memory.data.system) }}</li>
                  <li><label for="">lua:</label> {{ formatSizeHuman(nodeInfoTabs.memory.data.lua) }}</li>
                  <li><label for="">policy:</label> {{ nodeInfoTabs.memory.data.policy }}</li>
                  <li><label for="">dbSize: </label> {{ nodeInfoTabs.memory.data.dbSize }}</li>
                </ul>
              </el-tab-pane>
              <el-tab-pane name="slowlogs" :label="nodeInfoTabs.slowlogs.title">
                <span style="display: block" class="margin-bottom"><b>慢查询数量:</b>{{ nodeInfoTabs.slowlogs.data.length }}</span>
                <el-table
                  :data="slowlogs"
                  border
                  stripe
                  style="width: 100%"
                  size="mini"
                  height="400"
                >
                  <el-table-column
                    prop="id"
                    label="id"
                    width="80"
                  />

                  <el-table-column
                    label="timeStamp"
                    sortable
                    width="150"
                  >
                    <template slot-scope="scope">
                      <span>{{ parseTime(scope.row.timeStamp) }}</span>
                    </template>
                  </el-table-column>

                  <el-table-column
                    prop="executionTime"
                    label="executionTime"
                    sortable
                    width="140"
                  />

                  <el-table-column
                    label="args"
                  >
                    <template slot-scope="scope">
                      <span>{{ scope.row.args ? scope.row.args.join(' '): '' }}</span>
                    </template>
                  </el-table-column>
                  <el-table-column
                    fixed="right"
                    label="操作"
                    width="150"
                  >
                    <template slot-scope="scope">
                      <!--                      <el-button type="text" class="text-danger" size="small" @click="killQuery(scope.row.id)">kill</el-button>-->
                    </template>
                  </el-table-column>
                </el-table>
                <!--分页组件-->
                <el-pagination
                  :current-page="nodeInfoTabs.slowlogs.input.currentPage"
                  :page-size="nodeInfoTabs.slowlogs.input.pageSize"
                  layout="total, sizes, prev, pager, next"
                  :total="nodeInfoTabs.slowlogs.data.length"
                  @size-change="handleNodeInfoTabSizeChange"
                  @current-change="handleNodeInfoTabCurrentChange"
                />
              </el-tab-pane>
            </el-tabs>
          </el-col>
        </el-row>

      </el-tab-pane>
      <el-tab-pane name="keyscan" label="数据查询">
        <el-row>
          <el-col>
            <el-form inline size="mini">
              <el-form-item label="类加载器">
                <el-select v-model="tabs.keyscan.input.serializerParam.classloader" style="width: 150px">
                  <el-option
                    v-for="classloader in classloaders"
                    :key="classloader"
                    :value="classloader"
                    :label="classloader"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="key">
                <el-select v-model="tabs.keyscan.input.serializerParam.keySerializer" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer" />
                </el-select>
              </el-form-item>
              <el-form-item label="value">
                <el-select v-model="tabs.keyscan.input.serializerParam.value" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer" />
                </el-select>
              </el-form-item>
              <el-form-item label="hashKey">
                <el-select v-model="tabs.keyscan.input.serializerParam.hashKey" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer" />
                </el-select>
              </el-form-item>
              <el-form-item label="hashValue">
                <el-select v-model="tabs.keyscan.input.serializerParam.hashValue" style="width: 100px;">
                  <el-option v-for="serializer in serializers" :key="serializer" :value="serializer" :label="serializer" />
                </el-select>
              </el-form-item>

              <el-form-item>
                <el-button type="text" size="mini" @click="localStorageConfig"> <i class="fa fa-floppy-o" aria-hidden="true" /></el-button>
              </el-form-item>

            </el-form>
          </el-col>
        </el-row>

        <!-- keyscan -->
        <el-form :inline="true" @submit.native.prevent>
          <el-form-item>
            <el-checkbox v-model="tabs.keyscan.input.search.wildcardLeft">左模糊</el-checkbox>
            <el-checkbox v-model="tabs.keyscan.input.search.wildcardRight">右模糊</el-checkbox>
            <el-checkbox v-model="tabs.keyscan.input.search.fast">单KEY</el-checkbox>
          </el-form-item>
          <el-form-item>
            <el-input
              v-model="tabs.keyscan.input.keyScanParam.pattern"
              style="width: 380px"
              size="small"
              placeholder="输入 key 发起搜索"
              clearable
              suffix-icon="el-icon-search"
              @keyup.enter.native="scanKey"
            />
          </el-form-item>
          <el-form-item label="超时(ms)">
            <el-input v-model="tabs.keyscan.input.search.timeout" :disabled="tabs.keyscan.input.search.fast" size="small" style="width: 60px" />
          </el-form-item>
          <el-form-item>
            <el-button size="small" type="danger" @click="dropChoseKeys">批量删除</el-button>
          </el-form-item>
        </el-form>

        <el-row>
          <el-col :span="15">
            <el-table
              ref="keyScanTable"
              v-loading="tabs.keyscan.loading"
              :data="tabs.keyscan.keyScanResult.keys"
              border
              stripe
              style="width: 100%"
              size="mini"
              height="500"
            >
              <el-table-column
                type="selection"
                width="55"
              />
              <el-table-column
                type="index"
                width="50"
              />
              <el-table-column
                prop="type"
                label="type"
                width="90"
              />
              <el-table-column
                prop="key"
                label="key"
                width="450"
              />
              <el-table-column
                prop="ttl"
                label="ttl"
                width="90"
              />
              <el-table-column
                prop="length"
                label="length"
              />

              <el-table-column
                prop="pttl"
                label="pttl"
                width="90"
              />
              <el-table-column
                prop="slot"
                label="slot"
                width="100"
              />

              <el-table-column
                fixed="right"
                label="操作"
                width="150"
              >
                <template slot-scope="scope">
                  <el-button type="text" class="text-danger" size="small" @click="dropKeys(scope.row.key)">删除</el-button>
                  <el-button type="text" size="small" @click="readData(scope.row)">数据</el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-button-group>
              <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScan">重置</el-button>
              <el-button plain size="mini" :disabled="tabs.keyscan.keyScanResult.done" icon="el-icon-arrow-right" @click="nextPage">下一页</el-button>
            </el-button-group>
            cursor: {{ tabs.keyscan.keyScanResult.cursor || 0 }} nodeId: {{ tabs.keyscan.keyScanResult.nodeId }}
          </el-col>
          <el-col :span="9" class="padding-little-left data-show">
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'string'">
              <div class="panel panel-default">
                <div class="panel-heading">{{ tabs.keyscan.loadData.input.key }}({{ tabs.keyscan.loadData.keyObj.type }}) 数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body">
                  <div class="text">{{ tabs.keyscan.loadData.data }}</div>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'hash'">
              <p :title="tabs.keyscan.hashKeyScan.input.key" style="overflow-x: hidden;white-space: nowrap;text-overflow: ellipsis;">
                <el-button size="small" icon="el-icon-document-copy" type="text" class="margin-right" @click="copyKey(tabs.keyscan.hashKeyScan.input.key,$event)" />
                <b>key: </b>
                <span class="text-more">{{ tabs.keyscan.hashKeyScan.input.key }} </span>
              </p>
              <p class="padding-big-left"><b>数据量: </b>{{ tabs.keyscan.loadData.keyObj.length }}</p>
              <el-row>
                <el-col :span="18">
                  <el-input
                    v-model="tabs.keyscan.hashKeyScan.input.pattern"
                    suffix-icon="el-icon-search"
                    placeholder="搜索 hashKey "
                    size="small"
                    @keyup.enter.native="scanHashKey"
                  />
                </el-col>
                <el-col :span="5">
                  <el-button size="small">选中删除</el-button>
                </el-col>
              </el-row>
              <el-table
                ref="hashKeyScanTable"
                :data="hashScanResult"
                border
                stripe
                style="width: 100%"
                height="300"
                size="mini"
                highlight-current-row
              >
                <el-table-column
                  type="index"
                  width="50"
                />
                <el-table-column type="selection" width="55" />
                <el-table-column prop="field" label="field" />
                <el-table-column prop="value" label="value" />
                <el-table-column
                  fixed="right"
                  label="操作"
                  width="150"
                >
                  <template slot-scope="scope">
                    <el-button type="text" size="small" @click="dropFields(scope.row.field)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
              <el-button-group>
                <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScanHashKey">重置</el-button>
                <el-button plain size="mini" :disabled="tabs.keyscan.hashKeyScan.hashKeyScanResult.finish" icon="el-icon-arrow-right" @click="scanHashKeyNextPage">下一页</el-button>
              </el-button-group>
              cursor: {{ tabs.keyscan.hashKeyScan.hashKeyScanResult.cursor }}
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'list'">
              <p>
                <b>key:</b> {{ tabs.keyscan.loadData.input.key }}
                <b>数据量: </b>{{ tabs.keyscan.loadData.keyObj.length }}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <div class="margin-little-top">
                <el-checkbox v-model="tabs.keyscan.loadData.input.rangeParam.enable">开启</el-checkbox>
                <el-input-number
                  v-model="tabs.keyscan.loadData.input.rangeParam.start"
                  :disabled="rangeParamDisabled"
                  style="width: 120px"
                  size="small"
                  :min="0"
                  :max="tabs.keyscan.loadData.keyObj.length"
                />
                <el-input-number
                  v-model="tabs.keyscan.loadData.input.rangeParam.stop"
                  :disabled="rangeParamDisabled"
                  style="width: 120px"
                  size="small"
                  :min="0"
                  :max="tabs.keyscan.loadData.keyObj.length"
                />
                <el-button plain :disabled="rangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <div class="panel panel-default">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body">
                  <div class="text">{{ tabs.keyscan.loadData.data }}</div>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'set'">
              <p style="margin-top: 0">
                <b>key:</b> {{ tabs.keyscan.loadData.keyObj.key }}
                <b>数据量: </b>{{ tabs.keyscan.loadData.keyObj.length }}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <el-row class="">
                <el-col :span="14">
                  <el-input v-model="tabs.keyscan.set.input.otherKeys" placeholder="另外的 KEY,多个用逗号分隔 " size="small" class="margin-bottom" />
                </el-col>
                <el-col :span="10">
                  <el-button-group>
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" type="plain" size="small" @click="collectionOperation('inter')">交集</el-button>
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" type="plain" size="small" @click="collectionOperation('union')">并集</el-button>
                    <el-button :disabled="!!!tabs.keyscan.set.input.otherKeys" type="plain" size="small" @click="collectionOperation('diff')">差集</el-button>
                  </el-button-group>
                </el-col>
              </el-row>

              <!-- set 数据搜索-->
              <el-row>
                <el-col :span="3">
                  <el-checkbox v-model="tabs.keyscan.loadData.input.all" size="mini" @change="loadDataRequest">所有</el-checkbox>
                </el-col>
                <el-col :span="11">
                  <el-input
                    v-model="tabs.keyscan.loadData.input.keyScanParam.pattern"
                    :disabled="tabs.keyscan.loadData.input.all"
                    suffix-icon="el-icon-search"
                    placeholder="搜索 "
                    size="mini"
                    @keyup.enter.native="loadDataRequest"
                  />
                </el-col>
                <el-col :span="10">
                  <el-button-group>
                    <el-button :disabled="tabs.keyscan.loadData.input.all" plain size="mini" icon="el-icon-coordinate" @click="resetScanSetOrZSetKey">重置</el-button>
                    <el-button plain size="mini" :disabled="tabs.keyscan.set.scanResult.finish || tabs.keyscan.loadData.input.all" icon="el-icon-arrow-right" @click="scanSetKeyNextPage">下一页</el-button>
                  </el-button-group>

                </el-col>
              </el-row>
              <div class="panel panel-default margin-little-top">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body">
                  <p v-for="item in tabs.keyscan.loadData.data">{{ item }}</p>
                </div>
              </div>
            </template>
            <template v-if="tabs.keyscan.loadData.keyObj.type === 'zset'">
              <p style="margin-top: 0">
                <b>key:</b> {{ tabs.keyscan.loadData.keyObj.key }}
                <b>数据量: </b>{{ tabs.keyscan.loadData.keyObj.length }}
                <el-checkbox v-model="tabs.keyscan.loadData.input.all" @change="loadDataRequest">所有数据</el-checkbox>
              </p>
              <div class="margin-little-top">
                <label for="">区间范围查找:</label>
                <el-checkbox v-model="tabs.keyscan.loadData.input.rangeParam.enable">开启</el-checkbox>
                <el-input-number v-model="tabs.keyscan.loadData.input.rangeParam.start" :disabled="rangeParamDisabled" style="width: 120px" size="small" :min="0" :max="tabs.keyscan.loadData.keyObj.length" />
                <el-input-number v-model="tabs.keyscan.loadData.input.rangeParam.stop" :disabled="rangeParamDisabled" style="width: 120px" size="small" :min="0" :max="tabs.keyscan.loadData.keyObj.length" />
                <el-button plain :disabled="rangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <div class="margin-little-top">
                <label for="">分数范围查找:</label>
                <el-checkbox v-model="tabs.keyscan.loadData.input.scoreRangeParam.enable">开启</el-checkbox>
                <el-input-number v-model="tabs.keyscan.loadData.input.scoreRangeParam.min" :disabled="scoreRangeParamDisabled" style="width: 120px" :precision="2" size="small" :min="0" />
                <el-input-number v-model="tabs.keyscan.loadData.input.scoreRangeParam.max" :disabled="scoreRangeParamDisabled" style="width: 120px" :precision="2" size="small" :min="0" />
                <el-button plain :disabled="scoreRangeParamDisabled" size="small" @click="loadDataRequest">加载数据</el-button>
              </div>
              <el-row>
                <el-col :span="14">
                  <el-input
                    v-model="tabs.keyscan.loadData.input.keyScanParam.pattern"
                    suffix-icon="el-icon-search"
                    placeholder="搜索 "
                    size="small"
                    @keyup.enter.native="loadDataRequest"
                  />
                </el-col>
                <el-col :span="10">
                  <el-button-group>
                    <el-button plain size="mini" icon="el-icon-coordinate" @click="resetScanSetOrZSetKey">重置</el-button>
                    <el-button plain size="mini" :disabled="tabs.keyscan.zset.scanResult.finish" icon="el-icon-arrow-right" @click="scanZSetKeyNextPage">下一页</el-button>
                  </el-button-group>

                </el-col>
              </el-row>
              <div class="panel panel-default">
                <div class="panel-heading">数据展示
                  <el-button class="pull-right" size="small" type="text" style="padding: 0;" @click="showJson">JSON</el-button>
                </div>
                <div class="panel-body">
                  <p v-for="item in tabs.keyscan.loadData.data">{{ item }}</p>
                </div>
              </div>
            </template>
          </el-col>
        </el-row>

      </el-tab-pane>
    </el-tabs>

    <!-- json 格式化展示 -->
    <el-drawer
      :with-header="false"
      :visible.sync="drawer.visible"
      direction="rtl"
    >
      <json-editor :json="drawer.json" />
    </el-drawer>
  </div>
</template>

<script>
import core from '../../api/core'
import redis from '../../api/redis'
import JsonEditor from '@/components/JsonEditor'
import ListGroup from '@/components/ListGroup'
import { parseTime, formatSizeHuman } from '../../utils'

import clip from '@/utils/clipboard'
import ScrollPane from '@/layout/components/TagsView/ScrollPane' // use clipboard directly

export default {
  name: 'Redis',
  components: { ScrollPane, JsonEditor, ListGroup },
  data() {
    return {
      connParam: {
        connName: null,
        index: 0
      },
      connects: [],
      defaultProps: {
        children: 'slaveNodes',
        label: 'label'
      },
      tabs: {
        activeTabName: 'keyscan',
        dashboard: {
          connInfo: {
            redisRunMode: null,
            masterNodes: []
          }
        },
        keyscan: {
          loading: false,
          input: {
            search: {
              wildcardLeft: true,
              wildcardRight: true,
              timeout: -1,
              fast: false,
              nodeId: null
            },
            keyScanParam: {
              pattern: null,
              limit: 20,
              cursor: 0
            },
            serializerParam: {
              keySerializer: 'string',
              value: 'string',
              hashKey: 'string',
              hashValue: 'string',
              classloaderName: null
            }
          },
          set: {
            input: {
              otherKeys: null
            },
            scanResult: {
              cursor: 0
            }
          },
          zset: {
            // 专用于 zset 的输入和输出
            scanResult: {
              cursor: 0
            }
          },
          keyScanResult: {},
          hashKeyScan: {
            loading: false,
            input: {
              key: null,
              all: false,
              fields: [],
              pattern: '*',
              limit: 20,
              cursor: 0
            },
            hashKeyScanResult: {
              data: {},
              fields: [],
              cursor: 0
            }
          },
          loadData: {
            loading: false,
            keyObj: {},
            input: {
              key: null,
              all: false,
              keyScanParam: {
                pattern: '*',
                limit: 20,
                cursor: 0
              },
              rangeParam: {
                enable: false,
                start: 0,
                stop: 0
              },
              scoreRangeParam: {
                enable: false,
                min: 0,
                max: 0
              }
            },
            data: null
          }
        }
      },
      nodeInfoTabs: {
        activeTabName: 'memory',
        loading: false,
        nodeId: null,
        node: {},
        clients: {
          title: '客户端连接',
          data: [],
          input: {
            currentPage: 1,
            pageSize: 20
          }
        },
        memory: {
          title: '内存占用',
          data: {}
        },
        slowlogs: {
          title: '慢查询',
          data: [],
          input: {
            currentPage: 1,
            pageSize: 20
          }
        }
      },
      serializers: [],
      classloaders: [],
      drawer: {
        visible: false,
        json: null
      }
    }
  },
  computed: {
    dbsComputed() {
      const connInfo = this.tabs.dashboard.connInfo
      if (connInfo) {
        if (connInfo.redisRunMode === 'cluster') {
          return [0]
        }
        if (connInfo.masterNodes.length === 0) {
          return [0]
        }

        const masterNode = connInfo.masterNodes[0]

        const array = []
        for (let i = 0; i < masterNode.dbs; i++) {
          array.push(i)
        }
        return array
      }
      return [0]
    },
    clients() {
      const clients = this.nodeInfoTabs.clients
      if (!clients.data) {
        return []
      }
      const start = (clients.input.currentPage - 1) * clients.input.pageSize
      let end = clients.input.currentPage * clients.input.pageSize
      if (end > clients.data.length) {
        end = clients.data.length
      }
      return clients.data.slice(start, end)
    },
    slowlogs() {
      const slowlogs = this.nodeInfoTabs.slowlogs
      if (!slowlogs.data) {
        return []
      }
      const start = (slowlogs.input.currentPage - 1) * slowlogs.input.pageSize
      let end = slowlogs.input.currentPage * slowlogs.input.pageSize
      if (end > slowlogs.data.length) {
        end = slowlogs.data.length
      }
      return slowlogs.data.slice(start, end)
    },
    hashScanResult() {
      const hashScanResult = this.tabs.keyscan.hashKeyScan.hashKeyScanResult
      if (hashScanResult.data) {
        const values = []
        for (const field in hashScanResult.data) {
          values.push({ field: field, value: hashScanResult.data[field] })
        }
        return values
      }
      return []
    },
    rangeParamDisabled() {
      return this.tabs.keyscan.loadData.input.all || !this.tabs.keyscan.loadData.input.rangeParam.enable
    },
    scoreRangeParamDisabled() {
      return this.tabs.keyscan.loadData.input.all || !this.tabs.keyscan.loadData.input.scoreRangeParam.enable
    }
  },
  mounted() {
    this.reloadAllConnects()

    // 加载所有的序列化工具和类加载器工具
    core.classloaders().then(res => {
      this.classloaders = res.data
    })
    core.serializers().then(res => {
      this.serializers = res.data
    })

    // 加载本地保存的配置,如果之前有保存的话
    const config = this.$storeLocal.get('redis.config')
    if (config) {
      Object.assign(this.tabs.keyscan.input.serializerParam, config)
    }
  },
  methods: {
    switchTab(tab, event) {
      this.tabs.activeTabName = tab.name
      switch (tab.name) {
        case 'dashboard':

          break
      }
    },
    collectionOperation(op) {
      const otherKeys = this.tabs.keyscan.set.input.otherKeys.split(',')
      const keys = [...otherKeys, this.tabs.keyscan.loadData.input.key].join(',')
      redis.collectionMethods(this.connParam, keys, op, this.tabs.keyscan.input.serializerParam).then(res => {
        this.tabs.keyscan.loadData.data = res.data
      })
    },
    showJson() {
      try {
        if (typeof (this.tabs.keyscan.loadData.data) === 'object') {
          this.drawer.json = this.tabs.keyscan.loadData.data
        } else {
          this.drawer.json = JSON.parse(this.tabs.keyscan.loadData.data)
        }

        this.drawer.visible = true
      } catch (e) {
        this.$message(e.toString())
        console.log(this.tabs.keyscan.loadData.data)
      }
    },
    localStorageConfig() {
      this.$storeLocal.set('redis.config', this.tabs.keyscan.input.serializerParam)
      this.$message({ type: 'success', message: '个人配置保存成功,下次直接使用此配置' })
    },
    parseTime, formatSizeHuman,
    copyKey(text, event) {
      clip(text, event)
    },
    reloadAllConnects() {
      core.security.moduleConnectNames('redis').then(res => {
        this.connects = res.data
        if (this.connects && this.connects.length > 0) {
          this.switchConnect(this.connects[0])
        }
      })
    },
    switchIndex(index) {
      this.connParam.index = index
      this.loadConnect()
    },
    switchConnect(connect) {
      this.connParam.connName = connect
      this.loadConnect()
    },
    loadConnect() {
      // 加载当前连接信息
      redis.connInfo(this.connParam).then(res => {
        Object.assign(this.tabs.dashboard.connInfo, res.data)

        this.scanKey()
      })
    },
    scanKey() {
      const scanTabInput = this.tabs.keyscan.input

      const scanParam = Object.assign({}, scanTabInput.keyScanParam)
      // 如果需要支持模糊, 在key 两边加上 * 号
      if (scanParam.pattern) {
        if (scanTabInput.search.wildcardLeft) {
          scanParam.pattern = '*' + scanParam.pattern
        }
        if (scanTabInput.search.wildcardRight) {
          scanParam.pattern = scanParam.pattern + '*'
        }
      } else {
        scanParam.pattern = '*'
      }
      scanParam.timeout = scanTabInput.search.timeout
      scanParam.fast = scanTabInput.search.fast

      this.tabs.keyscan.loading = true
      redis.scan(this.connParam, scanParam, scanTabInput.serializerParam).then(res => {
        this.tabs.keyscan.loading = false
        this.tabs.keyscan.keyScanResult = res.data
      }).catch(res => {
        this.tabs.keyscan.loading = false
      })
    },
    dropChoseKeys() {
      const selection = this.$refs.keyScanTable.selection
      if (selection.length === 0) {
        this.$message('选中 key 来删除')
        return
      }
      const keys = selection.map(item => item.key)
      this.$confirm('确定删除 ' + selection.length + ' 个 key 吗,此操作不可逆?', '警告', { type: 'warning' }).then(() => {
        redis.delKeys(this.connParam, keys, this.tabs.keyscan.input.serializerParam).then(res => {
          this.scanKey()
        })
      }).catch(() => {})
    },
    dropChoseFields() {
      const selection = this.$refs.hashKeyScanTable.selection
      if (selection.length === 0) {
        this.$message('选中 key 来删除')
        return
      }
      const fields = selection.map(item => item.field)
      this.$confirm('确定删除 ' + selection.length + ' 个 key 吗,此操作不可逆?', '警告', { type: 'warning' }).then(() => {
        redis.delFields(this.connParam, this.tabs.keyscan.hashKeyScan.input.key, fields, this.tabs.keyscan.input.serializerParam).then(res => {
          this.scanHashKey()
        })
      }).catch(() => {})
    },
    // 扫描 key 时下一页
    nextPage() {
      const scanTabInput = this.tabs.keyscan.input

      scanTabInput.search.nodeId = this.tabs.keyscan.keyScanResult.nodeId
      scanTabInput.keyScanParam.cursor = this.tabs.keyscan.keyScanResult.cursor
      this.scanKey()
    },
    resetScan() {
      const scanTabInput = this.tabs.keyscan.input

      scanTabInput.search.nodeId = null
      scanTabInput.keyScanParam.cursor = '0'
      this.scanKey()
    },
    dropKeys(keys) {
      if (keys && typeof keys === 'string') {
        this.$confirm('确定删除 ' + keys + ' 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          console.log('删除 key', keys)
          redis.delKeys(this.connParam, [keys], this.tabs.keyscan.input.serializerParam).then(res => {
            this.scanKey()
          })
        }).catch(() => {
        })
      } else if (keys) {
        this.$confirm('再次确认,将删除' + keys.length + '个 key 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          redis.delKeys(this.connParam, keys, this.tabs.keyscan.input.serializerParam).then(res => {
            this.scanKey()
          })
        }).catch(() => {
        })
      }
    },
    readData(row) {
      const keyscanTab = this.tabs.keyscan

      keyscanTab.loadData.input.key = row.key
      keyscanTab.loadData.keyObj = row

      switch (row.type) {
        case 'string':
          // string 类型,直接加载数据
          redis.readData(this.connParam, row.key, keyscanTab.input.serializerParam).then(res => {
            keyscanTab.loadData.data = res.data
          })
          break
        case 'hash':
          keyscanTab.hashKeyScan.input.key = row.key
          this.resetScanHashKey()
          break
        case 'list':
          this.tabs.keyscan.loadData.input.rangeParam.start = 0
          this.tabs.keyscan.loadData.input.rangeParam.stop = 10
          this.loadDataRequest()
          break
        case 'set':
        case 'zset':
          this.resetScanSetOrZSetKey()
          break
      }
    },
    scanHashKey() {
      const hashKeyScan = this.tabs.keyscan.hashKeyScan
      hashKeyScan.loading = true
      redis.hscan(this.connParam, hashKeyScan.input, this.tabs.keyscan.input.serializerParam).then(res => {
        hashKeyScan.loading = false
        hashKeyScan.hashKeyScanResult = res.data
      }).catch(res => {
        hashKeyScan.loading = false
      })
    },
    scanHashKeyNextPage() {
      const hashKeyScan = this.tabs.keyscan.hashKeyScan
      hashKeyScan.input.cursor = hashKeyScan.hashKeyScanResult.cursor
      this.scanHashKey()
    },
    scanSetKeyNextPage() {
      const loadData = this.tabs.keyscan.loadData
      loadData.input.keyScanParam.cursor = this.tabs.keyscan.set.scanResult.cursor
      this.loadDataRequest()
    },
    scanZSetKeyNextPage() {
      const loadData = this.tabs.keyscan.loadData
      loadData.input.keyScanParam.cursor = this.tabs.keyscan.zset.scanResult.cursor
      this.loadDataRequest()
    },
    resetScanHashKey() {
      const keyscanTab = this.tabs.keyscan
      Object.assign(keyscanTab.hashKeyScan.input, { pattern: '*', cursor: '0', limit: 20 })
      this.scanHashKey()
    },
    resetScanSetOrZSetKey() {
      const loadData = this.tabs.keyscan.loadData
      Object.assign(loadData.input.keyScanParam, { pattern: '*', cursor: '0', limit: 20 })
      this.loadDataRequest()
    },
    dropFields(fields) {
      const keyscan = this.tabs.keyscan
      if (fields && typeof fields === 'string') {
        this.$confirm('确定删除 ' + fields + ' 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          redis.delFields(this.connParam, keyscan.hashKeyScan.input.key, [fields], keyscan.input.serializerParam).then(res => {
            this.scanHashKey()
          })
        }).catch(() => {
        })
      } else if (fields) {
        this.$confirm('再次确认,将删除' + fields.length + '个 field 此操作不可逆?', '警告', { type: 'warning' }).then(() => {
          redis.delFields(this.connParam, keyscan.hashKeyScan.input.key, fields, keyscan.input.serializerParam).then(res => {
            this.scanHashKey()
          })
        }).catch(() => {
        })
      }
    },
    loadDataRequest() {
      const loadData = this.tabs.keyscan.loadData
      loadData.loading = true
      redis.readData(this.connParam, loadData.input.key,
        this.tabs.keyscan.input.serializerParam, loadData.input.all,
        loadData.input.keyScanParam, loadData.input.rangeParam,
        loadData.input.scoreRangeParam).then(res => {
        loadData.loading = false
        if (loadData.keyObj.type === 'set' && 'cursor' in res.data) {
          this.tabs.keyscan.set.scanResult = res.data
          loadData.data = res.data.members
        } else if (loadData.keyObj.type === 'zset' && 'cursor' in res.data) {
          this.tabs.keyscan.zset.scanResult = res.data
          loadData.data = res.data.tuples
        } else {
          loadData.data = res.data
        }
      }).catch(res => {
        loadData.loading = false
      })
    },
    switchNodeInfoTab(tab, event) {
      this.nodeInfoTabs.activeTabName = tab.name

      switch (tab.name) {
        case 'clients':
          redis.clients(this.connParam, this.nodeInfoTabs.nodeId).then(res => {
            this.nodeInfoTabs.clients.data = res.data
          })
          break
        case 'memory':
          redis.memory(this.connParam, this.nodeInfoTabs.nodeId).then(res => {
            this.nodeInfoTabs.memory.data = res.data
          })
          break
        case 'slowlogs':
          redis.slowlogs(this.connParam, this.nodeInfoTabs.nodeId).then(res => {
            this.nodeInfoTabs.slowlogs.data = res.data
          })
          break
      }
    },
    clickNode(data, node, el) {
      this.loadNodeInfo(data)
    },
    loadNodeInfo(node) {
      this.nodeInfoTabs.nodeId = node.id
      this.nodeInfoTabs.node = node
      this.switchNodeInfoTab({ name: this.nodeInfoTabs.activeTabName })
    },
    killClient(client, nodeId) {
      redis.killClient(this.connParam, client, nodeId)
      this.switchNodeInfoTab({ name: 'clients' })
    },
    killQuery(id) {

    },
    handleNodeInfoTabSizeChange(val) {
      switch (this.nodeInfoTabs.activeTabName) {
        case 'clients':
          this.nodeInfoTabs.clients.input.pageSize = val
          break
        case 'slowlogs':
          this.nodeInfoTabs.slowlogs.input.pageSize = val
      }
    },
    handleNodeInfoTabCurrentChange(val) {
      switch (this.nodeInfoTabs.activeTabName) {
        case 'clients':
          this.nodeInfoTabs.clients.input.currentPage = val
          break
        case 'slowlogs':
          this.nodeInfoTabs.slowlogs.input.currentPage = val
      }
    }

  }
}
</script>

<style scoped>
.custom-tree-node{
  display: flex;
  align-items: center;
  width: 100%;
}
.custom-tree-node>button{
  margin-left: auto;
}
.memory-show{
  list-style-type: none;font-size: 15px;line-height: 2;
}
.memory-show li>label{
  display: inline-block;
  text-align: right;
  width: 80px;
}
.data-show .panel-body{
  min-height: 370px;
  max-height: 370px;
  overflow-y: scroll
}
</style>
